#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

// 全局变量定义
int g_unval;        // 未初始化的全局变量（BSS段）
int g_val = 100;    // 已初始化的全局变量（数据段）

int main(int argc, char *argv[], char *env[])
{
    const char *str = "helloworld";  // 字符串常量（只读数据段）
    
    // 打印代码段地址（函数地址）
    printf("code addr: %p\n", main);
    
    // 打印已初始化全局变量地址（数据段）
    printf("init global addr: %p\n", &g_val);
    
    // 打印未初始化全局变量地址（BSS段）
    printf("uninit global addr: %p\n", &g_unval);
    
    static int test = 10;  // 静态变量（数据段）
    
    // 动态内存分配（堆区）
    char *heap_mem = (char*)malloc(10);
    char *heap_mem1 = (char*)malloc(10);
    char *heap_mem2 = (char*)malloc(10);
    char *heap_mem3 = (char*)malloc(10);
    
    // 打印堆内存地址（注意：这里打印的是指针指向的地址，即堆内存的地址）
    printf("heap addr: %p\n", heap_mem);
    printf("heap addr: %p\n", heap_mem1);
    printf("heap addr: %p\n", heap_mem2);
    printf("heap addr: %p\n", heap_mem3);
    
    // 打印静态变量地址（数据段）
    printf("test static addr: %p\n", &test);
    
    // 打印栈内存地址（注意：这里打印的是指针变量本身的地址，即栈上的地址）
    printf("stack addr: %p\n", &heap_mem);
    printf("stack addr: %p\n", &heap_mem1);
    printf("stack addr: %p\n", &heap_mem2);
    printf("stack addr: %p\n", &heap_mem3);
    
    // 打印只读字符串地址（只读数据段）
    printf("read only string addr: %p\n", str);
    
    // 打印命令行参数地址（位于栈的高地址区域）
    int i = 0;
    for( i = 0; i < argc; i++)
    {
        printf("argv[%d]: %p\n", i, argv[i]);
    }
    
    // 打印环境变量地址（位于栈的高地址区域）
    for( i = 0; env[i]; i++)
    {
        printf("env[%d]: %p\n", i, env[i]);
    }
    
    return 0;
}
